package qc.common.core.utils;

/**
 * 密码工具类
 *
 * @author QuCheng Tech
 * @since 2023/9/6
 */
public class PasswordUtil {
    /**
     * 渠成密码加密次数，使用6次MD5加密
     *
     * @param
     * @return
     * @author QuCheng Tech
     * @since 2023/9/6
     */
    private static final int PASSWORD_ENCRYPT_COUNT = 0X6;

    /**
     * 渠成密码默认长度，默认为12为
     *
     * @param
     * @return
     * @author QuCheng Tech
     * @since 2023/9/6
     */
    private static final int PASSWORD_DEFAULT_LENGTH = 0XC;

    /**
     * 渠成密码最小长度，最小为8位
     *
     * @param
     * @return
     * @author QuCheng Tech
     * @since 2023/9/6
     */
    private static final int PASSWORD_MIN_LENGTH = 0X8;

    /**
     * 渠成密码最大长度，最大为15位
     *
     * @param
     * @return
     * @author QuCheng Tech
     * @since 2023/9/6
     */
    private static final int PASSWORD_MAX_LENGTH = 0XF;

    /**
     * 渠成密码默认强度，默认为3（字母、数值、特殊字符3种）
     *
     * @param
     * @return
     * @author QuCheng Tech
     * @since 2023/9/6
     */
    private static final int PASSWORD_DEFAULT_STRENGTH = 0X3;

    /**
     * 渠成密码最小强度
     *
     * @param
     * @return
     * @author QuCheng Tech
     * @since 2023/9/6
     */
    private static final int PASSWORD_MIN_STRENGTH = 0X2;

    /**
     * 渠成密码最大强度
     *
     * @param
     * @return
     * @author QuCheng Tech
     * @since 2023/9/6
     */
    private static final int PASSWORD_MAX_STRENGTH = 0X4;

    /**
     * 默认用户密码，在新增用户或重置密码时使用默认密码
     */
    public static final String DEFAULT_USER_PASSWORD = "88888888";

    /**
     * 密码过期天数，超过该天数提示修改
     */
    public static final short PASSWORD_EXPIRED_DAYS = 30;

    /**
     * 生成渠成用户密码的密文
     *
     * @param password 密码原文
     * @return java.lang.String
     * @author QuCheng Tech
     * @since 2023/9/6
     */
    public static String getQuChengEncryptPassword(String password) {
        return getMd5Encrypt(password, PASSWORD_ENCRYPT_COUNT);
    }

    /**
     * 生成默认密码的密文
     *
     * @return java.lang.String
     * @author QuCheng Tech
     * @since 2023/12/28
     */
    public static String getDefaultQuChengEncryptPassword() {
        return getQuChengEncryptPassword(DEFAULT_USER_PASSWORD);
    }

    /**
     * 使用MD5进行N次加密
     *
     * @param password 密码原文
     * @param count    加密次数
     * @return java.lang.String
     * @author QuCheng Tech
     * @since 2023/9/6
     */
    public static String getMd5Encrypt(String password, int count) {
        //加密次数至少为1
        if (count < 0x1)
            count = 0x1;

        String result = password;

        for (int i = 0; i < count; i++) {
            result = EncryptUtil.md5(result);
        }

        return result;
    }

    /**
     * 使用当前默认的密码长度和强度生成随机密码，返回密码明文
     *
     * @return java.lang.String
     * @author QuCheng Tech
     * @since 2023/9/6
     */
    public static String generateQuChengRandomPassword() {
        return generateRandomPassword(PASSWORD_DEFAULT_LENGTH, PASSWORD_DEFAULT_STRENGTH);
    }

    /**
     * 生成指定要求的密码原文
     *
     * @param length   密码长度
     * @param strength 强度数量，最小为2（小写字母、数字）、3（小写字母、数字、特殊字符）、4（大写字母、小写字母、数字、特殊字符）
     * @return java.lang.String
     * @author QuCheng Tech
     * @since 2023/9/6
     */
    public static String generateRandomPassword(int length, int strength) {
        if (length < PASSWORD_MIN_LENGTH)
            length = PASSWORD_MIN_LENGTH;
        if (length > PASSWORD_MAX_LENGTH)
            length = PASSWORD_MAX_LENGTH;

        if (strength < PASSWORD_MIN_STRENGTH)
            strength = PASSWORD_MIN_STRENGTH;
        if (strength > PASSWORD_MAX_STRENGTH)
            strength = PASSWORD_MAX_STRENGTH;

        int numericCount = 0x2;
        int specialCount = 0x0;
        int upperCount = 0x0;
        if (strength == 0x4) {
            //大写字母、小写字母、数字、特殊字符
            //总长度≥10：10~15：数字、特殊字符、大写字母数量使用2-3随机，长度不够的使用小写字母
            //总长度＜10:8~9：数字、特殊字符、大写字母数量使用1-2随机，长度不够的使用小写字母
            if (length >= 0xA) {
                numericCount = RandomUtil.generateIntValueByRange(0x2, 0x3);
                specialCount = RandomUtil.generateIntValueByRange(0x2, 0x3);
                upperCount = RandomUtil.generateIntValueByRange(0x2, 0x3);
            } else {
                numericCount = RandomUtil.generateIntValueByRange(0x1, 0x2);
                specialCount = RandomUtil.generateIntValueByRange(0x1, 0x2);
                upperCount = RandomUtil.generateIntValueByRange(0x1, 0x2);
            }
        } else if (strength == 0x3) {
            //小写字母、数字、特殊字符
            //数字、特殊字符使用1-3随机，长度不够的使用小写字母
            numericCount = RandomUtil.generateIntValueByRange(0x1, 0x3);
            specialCount = RandomUtil.generateIntValueByRange(0x1, 0x3);
            upperCount = 0x0;
        } else {
            //小写字母、数字
            //数字使用1-5随机，长度不够的使用小写字母
            numericCount = RandomUtil.generateIntValueByRange(0x1, 0x5);
            specialCount = 0x0;
            upperCount = 0x0;
        }
        //最后根据密码总长度计算小写字母长度
        int lowerCount = length - numericCount - specialCount - upperCount;
        //System.out.println("length=" + length + " numericCount=" + numericCount + " specialCount=" + specialCount + " upperCount=" + upperCount + " lowerCount=" + lowerCount);

        //组合生成的密码顺序，可以按照固定顺序，也可以按照随机顺序
        String numericString = RandomUtil.generateNumeric(numericCount);
        String specialString = RandomUtil.generateSpecialChars(specialCount);
        String upperString = RandomUtil.generateUpperCaseLetters(upperCount);
        String lowerString = RandomUtil.generateLowerCaseLetters(lowerCount);

        //密码至少有小写字母和数字
        String result = "";
        if (upperCount > 0x0)
            result = upperString;
        if (specialCount > 0x0)
            result = result.concat(specialString);
        if (lowerCount > 0x0)
            result = result.concat(lowerString);
        if (numericCount > 0x0)
            result = result.concat(numericString);

        return result;
    }
}
